在程式語言中,比較兩個值的相等性是一個常見的操作。在昨天提到的 JavaScript 運算子的種類中,比較運算子
就是拿來比較兩個值的相等性用的。而實際上 JavaScript 的相等比較主要還分成 嚴格相等(strict equality)
和 寬鬆相等(loose equality)
,這兩種比較方式的規則並不太一樣。另外在比較過程中可能會出現 隱含轉型
的行為。以上是本篇文章的主題。那我們開始吧。
首先,要先知道用於比較相等性的運算子如下。===
嚴格相等運算子==
寬鬆相等運算子!==
嚴格不相等運算子(結果與 ===
相反)!=
寬鬆不相等運算子(結果與 ==
相反)
嚴格相等(strict equality)
,或稱為 強相等
,使用 ===
運算子來比較兩個值。只有在兩個值的型別和值都相同的情況下,嚴格相等才會回傳 true。另外,如果兩個值皆為數字,只要它們是 NaN 以外的同一值,或者 +0 和 -0,則為相等。
'5' === 5; // 回傳 false,因為型別不同
null === undefined; // 回傳 false,因為型別不同
false === 0; // 回傳 false,因為型別不同
7 === [7]; // 回傳 false,因為型別不同
寬鬆相等(loose equality)
,或稱為 弱相等
,使用 ==
運算子來比較兩個值。當使用寬鬆相等時, JavaScript 會在比較時會進行隱含的型別轉換,然後比較兩個值是否相等。這種比較通常會導致一些意想不到的結果,特別是在不同型別的值進行比較時。
其中 隱含轉型
是指 JavaScript 在某些操作中自動將一種類型的值轉換為另一種類型的值。
來看看以下例子:
'5' == 5; // 回傳 true,因為字串 '5' 會被隱含轉換成數字 5 再作比較
null == undefined; // 回傳 true,因為規範中寬鬆比較的 null 和 undefined 是相等的
false == 0; // 回傳 true,因為布林值 false 會被隱含轉換成數字 0 再作比較
7 == [7]; // 回傳 false,因為陣列 [7] 會先被隱含轉換成字串 '7',並接著嘗試轉換成數字 7 再作比較
[1, 2] == '1,2'; // true,因為陣列 [1, 2] 會被隱含轉換成字串 '1,2',再作比較
'' === false; // false,因為型別不同
'' == false; // true,因為空字串 '' 會被轉換成 false 再作比較
[] == ''; // true,因為空陣列 [] 會被隱含轉換成字串 '',再作比較
[1, 2] == true; // true,因為陣列 [1, 2] 會被轉換成字串 '1,2',又非空字串會被轉換成 true 再作比較
[] == false; // true,因為空陣列 [] 會被隱含轉換成字串 '',又空字串會被轉換成 false 再作比較
NaN == NaN; // false
+0 === -0; // true
let score;
console.log(score === undefined); // true
console.log(score === null); // false
console.log(score == undefined); // true
console.log(score == null); // true
const obj1 = { key: 'value' };
const obj2 = { key: 'value' };
const obj3 = obj2;
console.log(obj1 == obj2); // false,因為 obj1 和 obj2 是不同的物件參考
console.log(obj2 === obj3); // true,因為 obj2 和 obj3 是相同的物件參考
今天介紹了 嚴格相等(strict equality)
和 寬鬆相等(loose equality)
的差別,以及舉了一些例子來聊解 隱含轉型
是如何影響比較結果的。我是較少在使用寬鬆相等(==、!=)的比較方式,畢竟太「寬鬆」可能帶來一些淺在的問題,例如以下例子:
let totalNum = 0;
conet a = '5';
if(a == 5) {
totalNum = totalNum + a;
console.log(total); // 輸出字串的 '05'
}
此外更多規則可參考 MDN文件,
那麼今天就到這邊,我們明天見~